
from pymt import *
import math

class ENICEMenu(MTScatterWidget):
  def __init__(self, **kwargs):
    #print "MTTouchAndShowButton constructed"
    kwargs.setdefault('start_angle', 0)
    kwargs.setdefault('end_angle', 360)
    kwargs.setdefault('sub_buttons_radius_extra_spacing', 50)
    kwargs.setdefault('radius_difference', 50)
    kwargs.setdefault('scale_min', 0.5)
    kwargs.setdefault('scale_max', 2)
    
    self.start_angle = kwargs.get("start_angle")
    self.end_angle = kwargs.get("end_angle")
    self.sub_buttons_radius_extra_spacing = kwargs.get("sub_buttons_radius_extra_spacing")
    self.radius_difference = kwargs.get("radius_difference")
    self.layer_radius = {}
    self.sub_buttons = {}
    self.cb_kwargs = {}
    
    self.sub_button_parent_angle = []
    
    self.selected_sub_buttons = []
    
    if(self.start_angle >= self.end_angle):
      print "MTTouchAndShowButton: start_angle should be smaller than end_angle."
      self.start_angle = 0
      self.end_angle = 360
      
    kwargs.setdefault('do_scale',False)
      
    super(ENICEMenu, self).__init__(**kwargs)

  def add_sub_button(self, filename,**kwargs):
    kwargs.setdefault('callback_function', None)
    kwargs.setdefault('callback_kwargs', {})
    kwargs.setdefault('menu_parent', None)

    new_sub_button = MTImageButton(filename=filename)
    self.sub_buttons[new_sub_button] = kwargs.get("callback_function")
    self.cb_kwargs[new_sub_button] = kwargs.get("callback_kwargs")
    
    new_sub_button.menu_parent =  kwargs.get("menu_parent")
    new_sub_button.layer =  kwargs.get("layer")

    layer = 0
    has_menu_parent = new_sub_button.menu_parent
    while has_menu_parent is not None:
      layer+=1
      has_menu_parent = has_menu_parent.menu_parent
    
    #Set radius for each layer
    if layer not in self.layer_radius:
        self.layer_radius[layer] = 0
    self.layer_radius[layer] = max(self.layer_radius[layer], max(new_sub_button.width, new_sub_button.height))
    return new_sub_button
    
  def hide_sub_buttons(self,**kwargs):
    for sub_button in self.sub_buttons.keys():
      self.remove_widget(sub_button)
  
  def show_sub_buttons(self,**kwargs):
    #print "self.selected_sub_buttons", self.selected_sub_buttons

    self.num_of_layers = len(self.selected_sub_buttons) + 1
    #print "self.num_of_layers", self.num_of_layers
    
    for layer in range(0, self.num_of_layers):
        # if layer zero then show each of the sub buttons
        if layer == 0:
            layer_sub_buttons = filter((lambda x: x.menu_parent == None), self.sub_buttons.keys())
        else:
            layer_sub_buttons = filter((lambda x: x.menu_parent == self.selected_sub_buttons[layer - 1]), self.sub_buttons.keys())

        if(layer != 0):
          #print self.layer_radius[layer]
          if(len(layer_sub_buttons) > 0):
            angle = (self.selected_sub_buttons[layer - 1].angle)
            if(len(layer_sub_buttons) == 1):
              angle_increment = 0
            else:
              #print "Layer Radius: ",self.layer_radius[layer]
              angle = (self.selected_sub_buttons[layer - 1].angle) - (((len(layer_sub_buttons)-1)*self.layer_radius[layer])/2)
              angle_increment = self.layer_radius[layer]
          
        else:
          #print self.layer_radius[layer]
          if(len(layer_sub_buttons) > 0):
            angle = self.start_angle
            if(len(layer_sub_buttons) == 1):
              angle_increment = 0
              angle = (self.end_angle + self.start_angle) / 2.0
            else:
              if(self.end_angle - self.start_angle == 360):
                angle_increment = (self.end_angle - self.start_angle) / float(len(layer_sub_buttons))
              else:
                angle_increment = (self.end_angle - self.start_angle) / float(len(layer_sub_buttons) - 1)
            
        for sub_button in layer_sub_buttons:
          #calculate layer of each sub_button
          x = math.sin(angle * ( math.pi / 180.0) ) * (self.layer_radius[layer] + self.sub_buttons_radius_extra_spacing + (layer * self.radius_difference))
          y = math.cos(angle * ( math.pi / 180.0) ) * (self.layer_radius[layer] + self.sub_buttons_radius_extra_spacing + (layer * self.radius_difference))
          sub_button.pos = ((0 - (sub_button.width / 2)) + x, 0 - (sub_button.height / 2) + y)
          sub_button.angle = angle
          self.add_widget(sub_button)
          angle += angle_increment
  
  def on_touch_up(self, touch):
    #print "MTTouchUp"
    
    local_coords = self.to_local(touch.x, touch.y)
    v = Vector(local_coords[0], local_coords[1])
    
    for child in self.children:
    #checks if over a button
      if(child.collide_point(v[0], v[1])):
        #checks if button has no children, if true execute event else show sub_button children
        if self.sub_buttons[child] != None:
          #print "run function"
          self.hide_sub_buttons()
          #callback(touch)
          self.sub_buttons[child](touch,**self.cb_kwargs[child])
          self.parent.remove_widget(self)
        else:
            layer = 0
            has_menu_parent = child.menu_parent
            while has_menu_parent is not None:
              layer+=1
              has_menu_parent = has_menu_parent.menu_parent
            del self.selected_sub_buttons[layer:]
            
        self.selected_sub_buttons.append(child)
        self.hide_sub_buttons()
        self.show_sub_buttons(menu_parent=child)
    super(ENICEMenu, self).on_touch_up(touch)
     
  def collide_point(self, x, y):
    if not self.visible:
        return False
    local_coords = self.to_local(x, y)
    v = Vector(local_coords[0], local_coords[1])
    if(Vector.length(v)<=50):
      #print "inside"
      return True
    #else:
    return False
  

  def draw(self,**kwargs):
    set_color(.094, .572, .858, .255)
    for layer in range(0,self.num_of_layers):
      #drawCircle(pos=(self.x,self.y),radius=(self.layer_radius[layer] + self.sub_buttons_radius_extra_spacing + (layer * self.radius_difference)))
      drawCircle(pos=(0,0),radius=(self.layer_radius[layer] + self.sub_buttons_radius_extra_spacing + (layer * self.radius_difference)),linewidth=8)
    super(ENICEMenu, self).draw(**kwargs)



class MTGestureDetector(MTGestureWidget):
    def __init__(self, gdb, **kwargs):
        super(MTGestureDetector, self).__init__(**kwargs)
        self.gdb = gdb
        
    def on_touch_down(self, touch):
        touch.userdata['desktop.gesture'] = list(touch.pos)
        return super(MTGestureDetector, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        if 'desktop.gesture' in touch.userdata:
            touch.userdata['desktop.gesture'] += list(touch.pos)
        return super(MTGestureDetector, self).on_touch_move(touch)
        
    def on_gesture(self, gesture, touch): #fired after touch event
        try:
            x, y = self.to_local(*touch.pos)
            score, best = self.gdb.find(gesture, minscore=.8)
        except Exception, e:
            return
        
        if best.id == 'NUI-wave':
            print("### NUI-Wave ###")
            angle = gesture.get_rigid_rotation(best)
            self.launchMenu(x,y,angle)
    
    def launchMenu(self, x, y,angle):
        print("Launch_Core")
        button = ENICEMenu(pos=(x,y),rotation=angle) # start_angle = 0, end_angle = 360,pos=(w.width / 2, w.height / 2),rotation=angle
        w.add_widget(button)
    
        # example sub_buttons
        one = button.add_sub_button("ticons/1.png")


        button.show_sub_buttons()
                
    def draw(self):
        # draw gestures
        set_color(1, 1, 1, .6)
        for touch in getCurrentTouches():
            if not 'desktop.gesture' in touch.userdata:
                continue
            drawLine(touch.userdata['desktop.gesture'], width=5.)

def gesture_add_default(gdb):        
    # NUI-wave
    g = gdb.str_to_gesture('eNq1lttqHEcURd/7R6SXiHO//IDzGtAHBMcehIljDZoxxH+f3eXRdCskKSVBQiDBTK2urnVqn3P76fjtt/Pdw+F0/vp0WH68/D3ScvvxyMv9zen89Pjr4XSzHGW5/XzU5fYvV9yPry1HW9c51h0fP305r8tiXZZ/s+yn9VvLsdZVjVXfsIBpefcD3UmIsXqGRlJY53K6v/l9/ZzH566cxmSqUe0kupx+ef+PT2EZL6XLw+URXKwq1i7lXVpAPPx3+nh19o0u5MJRZumcSv2/6DHoeaUTNyepKouWcOaOziWSLl3uphGvoA8B3N/pgFtpp6iZaZp3x0a3xosRNl1SRh0xpcsoJuFnOmN3wu6VUZQELRvccS6R3GQW4tVz+JAq+jbw4VT8Cs/I9GC8u7CY1A4O0xmc5WRUrjKHD6WSz3ARo5RmYm5D4fgGR2lSi7alkBK7zeHDqFyNimNnEa1Nirq0XakrXc5K2ztzvnEdPpVfwRbL9hRvL+eIVxS6Dp969SlM7kBHkDcV7SqRn5+I68TwPvepw6duPtk7rEhw5oqwsR1cu1DqzpZJXjo/ch0+Nd8GPnzqdkPd2bWf76Lnrs6pG06DqTWQPO5Tug2jxrt0+VP48g4f7mIlyS6pmllz/pBqW/Jie6nZRNGs1cq7w6GX4Ug0TxgbXm2XvZHF1YVcRAmOgB140OHDJI2MEXKa4a/Y/jBr+Vb44db6ihepkM5GRqnUNcLWo/GSwOlzw2+6zuE+1PqmFp2hJQm7L8LFtdjogT6oKCwRD0O6zS+UD7G+iUVOJSNQ0HbQemR3Moxgcyorx01FWs6t+vdhYrMqHdxAX0BpGzwzuUClxnXoeYb5UOqbUvQM5hDUZDRSfjsV8ZdGc84ePn3zyQj25nZDL0VHlR0cV9WIQGVBSPA8CGL4DH4b+NAZu3uajSpnU5BCBZlzpasrGhJhColgdL15KcbwGZtP5Na+FNVyo1fCaSG8DNNH1TzDYhiNa/ySWpWiYSIMRdE86wqHzn9XLTGMxpa+mLgK9XyZs1AvGxsdryoKyUmJf+fwHEZzOh6BHSh8YShJk5ael2IOoblNR425DU0jVD00a3cmUetIhD6uyN7ucffX3/ub8+Pnw9P7Lx8OGL5x51YMvfzhdTa/7ODn49Pjx68fzuuXfXlnd4FpBhdK1kMThD7Ad38A6q5S7Q==')
    g.label = 'NUI-wave'
    g.id = 'NUI-wave'
    gdb.add_gesture(g)
    
def do_something(self):
  print "do something"

def do_other(self):
  print "do other"
    
if __name__ == '__main__':
    # Create background window
    w = MTWindow()
    #ctx = MTContext()
    
    #w.wallpaper = '../resources/black (copy).jpg'
    #w.wallpaper_position = 'scale'
    
    #kinetics = MTKinetic()
    #w.add_widget(kinetics)
    
    #widget1 = MTWidget()
    #kinetics.add_widget(widget1)
    
    # Create and fill gesture database
    gdb = GestureDatabase()
    gesture_add_default(gdb)
    
    # add gesturing
    gesturing = MTGestureDetector(gdb)
    w.add_widget(gesturing)

    runTouchApp()
